home *** CD-ROM | disk | FTP | other *** search
- #ifndef VMS
- # error -- CKVTIO.C is used only on the VMS(tm) or OpenVMS(tm) Operating System
- #endif /* VMS */
-
- #ifdef __ALPHA
- # define CKVTIO_OS_ARCH_STRING " OpenVMS(tm) AXP(tm)";
- #else
- # ifdef VAX
- # module ckvtio "2.0-056"
- # define CKVTIO_OS_ARCH_STRING " OpenVMS(tm) VAX(tm)";
- # else
- # ifdef __GNUC__
- # define CKVTIO_OS_ARCH_STRING " OpenVMS(tm) VAX(tm) (GCC)";
- # else
- # error -- CKVTIO.C unknown architecture, neither VAX(tm) nor AXP(tm)
- # endif /* __GNUC__ */
- # endif /* VAX */
- #endif /* __ALPHA */
- /*
- Module version number and date.
- Also update the module number above accordingly.
- */
- char *ckxv = "Communications I/O 2.0(056), 8 Aug 93";
- /*
- This is the default architecture and operating system herald string.
- It is redetermined dynamically in sysinit() below.
- */
- char *ckxsys = CKVTIO_OS_ARCH_STRING;
-
- /* C K V T I O -- Terminal and Interrupt Functions for VAX/VMS */
-
- /* C-Kermit interrupt, terminal control & i/o functions for VMS systems */
-
- /*
- Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
- Columbia University Academic Information Systems, New York City.
-
- Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
- York. The C-Kermit software may not be, in whole or in part, licensed or
- sold for profit as a software product itself, nor may it be included in or
- distributed with commercial products or otherwise distributed by commercial
- concerns to their clients or customers without written permission of the
- Office of Kermit Development and Distribution, Columbia University. This
- copyright notice must not be removed, altered, or obscured.
- */
-
- /* Edit History
- *
- * Originally adapted to VMS by:
- * Stew Rubenstein, Harvard University Chemical Labs, 1985.
- *
- * Cast of characters:
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * wb William Bader Lehigh University
- * mab Mark Buda DEC
- * fdc Frank da Cruz Columbia U
- * HG Hunter Goatley Western KY U
- * jh James Harvey Indiana / Purdue U
- * tmk Terry Kennedy St Peters College
- * MM Martin Minow DEC
- * DS Dan Schullman DEC
- * LT Lee Tibbert DEC
- * js James Sturdevant
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * 006 8-May-85 MM Got rid of "typeahead buffer" code as it didn't
- * solve the problem of data overruns at 4800 Baud.
- * Added vms "read a char" routine that checks for
- * CTRL/C, CTRL/Z, etc.
- * 007 16-May-85 fdc Changed calling convention of ttopen(), make it
- * set value of its argument "lcl", to tell whether
- * C-Kermit is in local or remote mode.
- * 008 11 Jun 85 MM Fix definition of CTTNAM
- * 009 18 Jun 85 fdc Move def of CTTNAM to ckcdeb.h so it can be shared.
- * 010 25 Jun 85 MM Added sysinit() to open console.
- * 011 5 Jul 85 DS Treat hangup of closed line as success.
- * 012 11 Jul 85 fdc Add gtimer(), rtimer() for timing statistics.
- * 013 14 Sep 87 fdc Add parity strip to ttinl(), add syscleanup().
- * 014 14 Feb 89 mab Make break REALLY work. Add IOSB's to all QIO's.
- * 015 26 Feb 89 mab Add dcl exit handler and minor cleanup
- * 016 23-Mar-89 mab Add IO$M_BREAKTHRU to IO$_WRITEVBLK.
- * Add zchkspd() function to check for valid speed.
- * 017 04-Apr-89 mab Fix some minor bugs to local/remote code
- * 018 23-Apr-89 mab Add some of Valerie Mates' parity changes.
- * 019 25-Apr-89 mab Change baud to 110 for V4.x break routine as
- * 50 baud is not supported on most Muxes by VMS.
- * 020 13-Jun-89 mab Fix on exquota problem on qiow(readvblk)
- * 021 08-Jul-89 mab Add ^C/^Y abort server mode code.
- * 022 11-May-90 mab Add V5A code
- * 023 20-Jul-90 wb Add support for old VAX C and VMS versions
- * 024 22-Sep-90 wb Fixes to cps/bps confusion
- * 025 26-Sep-90 tmk Fix the ztime() function
- * 026 29-Sep-90 tmk Edit 024 cause a server command to give some blither-
- * ings about unsupported line speeds. Added a simple hack
- * to exit quietly if the passed speed is 0. Adventurous
- * maintainers may want to look in ttpkt(), where ttsspd()
- * is being called with a value of -1/10.
- * 027 11-Oct-90 fdc Made ttol return number of chars successfully written.
- * Made ztime() use ctime() in all cases.
- * Another fix (from tmk) for bps/cps confusion.
- * Wrapped source lines longer than 80 characters.
- * 028 18-Oct-90 fdc Added comments to concb() and vms_getchar() to show
- * how to make Ctrl-C trap work. Didn't actually do it,
- * though, because Ctrl-Y apparently still can't be caught.
- * Also, more minor reformatting. Adjust time() declare.
- * Added support for automatic parity sense in ttinl(),
- * within #ifdef PARSENSE conditionals. Built with PARSENSE
- * defined, works ok.
- * 029 5-Apr-91 fdc Extensive reworking of many routines to allow for
- * network connections, addition of TGV MultiNet support.
- * 030 31-Aug-91 tmk Fix problem with INPUT statements not timing out due to
- * extraneous rtimer() inside gtimer().
- * 032 6-Nov-91 fdc Correct parity problem.
- * 032 6-Nov-91 fdc Cosmetic cleanup in sysinit().
- * 033 14-Jan-91 fdc Fix to get_qio_maxbuf_size to prevent crashes:
- * remove "&" from "!test_qio(ttychn,max,&tmpbuf)",
- * from John Schultz at 3M.
- * 034 8-Feb-92 fdc Don't change EIGHTBIT setting in ttvt, concb, or conbin.
- * Set EIGHTBIT in ttpkt only if parity is not NONE. From
- * Alan Robiette, Oxford U, UK.
- * 035 10-Jun-92 fdc Added code from Ray Hunter of The Wollongong Group to
- * support both WIN/TCP and TGV Multinet. Network section
- * of contti() redone to eliminate polling loop. It's
- * infinitely faster.
- * 036 11-Jun-92 tmk Fixed up edit 034 so 8-bit characters could be passed
- * in connect mode.
- * 037 19-Jun-92 fdc Totally rewrote all the serial input and mode-setting
- * routines in this module to use nonblocking, fully
- * buffered input and to share a common buffer. All
- * serial-line input is localized to a single routine,
- * txbufr(), which, in turn is known only to ttinc(). The
- * other input routines, ttxin() and ttinl(), simply call
- * ttinc(). ttchk() and ttflui() are totally cognizant of
- * the buffer. ttinl() now recognizes packets with
- * printable start characters and/or lacking terminators,
- * so VMS C-Kermit can now engage in "Doomsday Kermit"
- * protocol. ttvt() and ttpkt() were merged into a single
- * new (static) routine, ttbin(), which no longer puts the
- * device into PASALL mode (which defeats flow control).
- * Added ttsndlb() to send a Long BREAK. Much fine-tuning,
- * testing, and filling-in remains to be done, including
- * (a) make ttopen() and ttclos() aware of LAT devices; (b)
- * check remaining BYTLM quota before issuing a read, (c)
- * integrate network and serial buffers, and much more.
- * Anyway, this code seems to run faster than ever before,
- * and for the first time I can actually use sliding
- * windows AND long packets on my 8-year old MicroVAX-II.
- * 038 28-Jun-92 tmk Additional work on edit 37, general cleanup of old defs.
- * 039 1-Jul-92 wb Changes for VMS 4.4.
- * 040 4-Jul-92 tmk Add modem signal support (ttgmdm routine).
- * 041 4-Jul-92 tmk Add tgetent(), worker routine for el-cheapo curses.
- * 042 4-Jul-92 jh Enable typeahead in ttbin().
- * 043 21-Aug-92 fdc Make default flow control be KEEP instead of Xon/Xoff.
- * 044 6-Sep-92 fdc Put default flow back to Xon/Xoff, but allow KEEP to be
- * used to restore device's original flow-control setting.
- * 045 23-Sep-92 fdc Add sleep(1) to tthang(). Seems to fix HANGUP command.
- * Suggested by Lee Tibbert. Change ttbin() to use global
- * flow variable rather than its flow parameter for setting
- * flow control, to ensure the desired type of flow control
- * is used during DIAL operations.
- * 046 26-Sep-92 fdc Change sleep(1) in tthang() to sleep(3). Annoying but
- * necessary. IO$M_HANGUP takes about 3 seconds, but the
- * sys$qiow() function returns immediately instead of
- * waiting for the action to complete.
- * 047 08-Oct-92 HG Add call to sys$alloc in ttopen() to prevent user with
- * SHARE from getting port in use. Some add'l cleanup.
- * 048 12-Oct-92 LT Minor changes to support DEC TCP/IP (nee UCX).
- * 049 25-Oct-92 fdc Adapt cancio() to DEC TCP/IP.
- * Remove superfluous ttflui() call from ttpkt().
- * Add code from Lee Tibbert to sysinit() to figure out OS
- * and architecture name at runtime.
- * 050 18-Nov-92 fdc Read from comm device in 1024-byte chunks, rather than
- * trusting the qio_maxbuf_size. This should reduce BYTLM
- * quota-exceeded errors. Suggested by tmk as a temporary
- * workaround.
- * 051 10-May-93 fdc Add support for SET TRANSFER CANCELLATION.
- * 052 16-May-93 fdc Change VMSTCPIP to TCPIPLIB to agree with new CKCNET.H.
- * 053 16-May-93 fdc ANSIfication for GNU CC, from James Sturdevant.
- * 054 08-Jun-83 fdc Add TT$M_LOCALECHO and TT$M_ESCAPE to the terminal modes
- * we handle, to prevent "getty babble" with modems, VAX
- * PSI, etc.
- * 055 16-Jun-93 fdc Edit 054 only affected ttbin(). This edit does the same
- * for conbin() and concb(). Fixes double echoing in
- * command mode when coming in via VAX PSI.
- * 056 8-Aug-93 fdc Add types to all function declarations.
- */
-
- /*
- Variables available to outside world:
-
- dftty -- Pointer to default tty name string, like "/dev/tty".
- dfloc -- 0 if dftty is console(remote), 1 if external line(local).
- dfprty -- Default parity
- dfflow -- Default flow control
- ckxech -- Flag for who echoes console typein:
- 1 - The program (system echo is turned off)
- 0 - The system (or front end, or terminal).
- functions that want to do their own echoing should check this flag
- before doing so.
-
- backgrd
- Flag indicating program not executing interactively.
- Used to ignore INT and QUIT signals, suppress messages, etc.
- vms_status
- Status returned by most recent VMS system service,
- can be used for error reporting.
-
- Functions for assigned communication line (either external or console tty):
-
- ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
- ttclos() -- Close & reset the tty, releasing any access lock.
- ttpkt(speed,flow) -- Put the tty in packet mode and set the speed.
- ttvt(speed,flow) -- Put the tty in virtual terminal mode.
- or in DIALING or CONNECTED modem control state.
- ttinl(dest,max,timo) -- Timed read line from the tty.
- ttinc(timo) -- Timed read character from tty.
- ttchk() -- See how many characters in tty input buffer.
- ttxin(n,buf) -- Read n characters from tty (untimed).
- ttol(string,length) -- Write a string to the tty.
- ttoc(c) -- Write a character to the tty.
- ttflui() -- Flush tty input buffer.
- tt_cancel() -- Cancel any asynch I/O to tty
- */
-
- /*
- Functions for console terminal:
- congm() -- Get console terminal modes.
- concb(esc) -- Put the console in single-character wakeup mode with no echo.
- conbin(esc) -- Put the console in binary (raw) mode.
- conres() -- Restore the console to mode obtained by congm().
- conoc(c) -- Unbuffered output, one character to console.
- conol(s) -- Unbuffered output, null-terminated string to the console.
- conola(s) -- Unbuffered output, array of lines to the console, CRLFs added.
- conxo(n,s) -- Unbuffered output, n characters to the console.
- conchk() -- Check if characters available at console (bsd 4.2).
- Check if escape char (^\) typed at console (System III/V).
- coninc(timo) -- Timed get a character from the console.
- conint() -- Enable terminal interrupts on the console if not background.
- connoi() -- Disable terminal interrupts on the console if not background.
- contti() -- Get a character from either console or tty, whichever is first.
-
- Time functions
-
- msleep(m) -- Millisecond sleep
- ztime(&s) -- Return pointer to date/time string
- rtimer() -- Reset elapsed time counter
- gtimer() -- Get elapsed time
- */
-
- /* Includes */
- #include "ckcdeb.h" /* Formats for debug() */
- #include "ckcasc.h"
- #include "ckcker.h"
-
- #include "ckvvms.h"
-
- #include <stdio.h> /* Unix Standard i/o */
- #include <signal.h> /* Interrupts */
- #include <setjmp.h> /* Longjumps */
- #include <iodef.h>
- #include <ttdef.h>
- #include <tt2def.h>
- #include <ssdef.h>
- #include <descrip.h>
- #include <dvidef.h>
- #include <dcdef.h>
- #include <devdef.h>
- #include <time.h>
- #include <syidef.h>
-
- /* lt 1992-10-08 Begin
- */
- #ifndef __ALPHA
- # ifndef __GNUC__
- # define void int
- # endif /* __GNUC__ */
- #endif /* __ALPHA */
- /* lt 1992-10-08 End
- */
-
- #if defined(VMS_V40) || defined(VMS_V42) || defined(VMS_V44) /* No starlet */
- #define IO$_TTY_PORT 41
- #else
- #include <starlet.h>
- #endif /* (Old VMS) */
-
- /* Macros */
-
- #define xx_inc(timo) (--ttxbn>=0?ttxbuf[ttxbp++]:txbufr(timo))
-
- /* Declarations */
-
- #ifndef __ALPHA
- #ifndef MULTINET
- time_t time();
- #endif
- #endif
- char *ctime(); /* Convert to asctime() string */
-
- void dcl_exit_h(); /* Exit handler */
- unsigned long int vms_assign_channel();
- VOID tt_cancel();
-
- /* dftty is the device name of the default device for file transfer */
- /* dfloc is 1 if dftty is the user's console terminal, 0 if an external line */
-
- char *dftty = CTTNAM;
- int dfloc = 0; /* Default location is local */
- int dfprty = 0; /* Parity (0 = none) */
- int ttprty = 0; /* Parity in use */
- int ttpflg = 0; /* Parity not sensed yet. */
- int backgrd = 0; /* Running in "background" (no tty) */
- static int ttpmsk = 0377;
- int ttmdm = 0; /* Modem in use. */
- int dfflow = FLO_XONX; /* Default flow control is Xon/Xoff */
- int batch = 0; /* Assume interactive */
- int ttcarr = CAR_AUT; /* Carrier Handling Mode */
- int tvtflg = 0; /* Flag that ttvt has been called */
- long ttspeed = -1; /* For saving speed */
- int ttflow = -9; /* For saving flow */
-
- int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
-
- unsigned int vms_status; /* Used for system service return status */
-
- /* Structures used within this module */
-
- #ifndef TT$C_BAUD_38400
- #define TT$C_BAUD_38400 0x11
- #endif /* TT$C_BAUD_38400 */
-
- static struct {
- unsigned char dec;
- unsigned short int line;
- } ttspeeds[] = {
- {TT$C_BAUD_50, 5},
- {TT$C_BAUD_75, 7},
- {TT$C_BAUD_110, 11},
- {TT$C_BAUD_134, 13},
- {TT$C_BAUD_150, 15},
- {TT$C_BAUD_300, 30},
- {TT$C_BAUD_600, 60},
- {TT$C_BAUD_1200, 120},
- {TT$C_BAUD_1800, 180},
- {TT$C_BAUD_2000, 200},
- {TT$C_BAUD_2400, 240},
- {TT$C_BAUD_3600, 360},
- {TT$C_BAUD_4800, 480},
- {TT$C_BAUD_7200, 720},
- {TT$C_BAUD_9600, 960},
- {TT$C_BAUD_19200, 1920},
- {TT$C_BAUD_38400, 3840},
- {0, 0} };
-
- /* Declarations of variables global within this module */
-
- static long tcount = 0; /* For timing statistics */
-
- static char brkarray[] = { /* For simulating BREAK */
-
- '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
- '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
- };
-
- int ttyfd = -1; /* TTY file descriptor */
-
- static int conif = 0, /* Console interrupts on/off flag */
- conclass = 0, /* Console device type */
- cgmf = 0, /* Flag that console modes saved */
- xlocal = 0, /* Flag for tty local or remote */
- ttychn = 0, /* TTY i/o channe; */
- conchn = 0, /* Console i/o channel */
- con_queued = 0, /* console i/o queued in contti() */
- tt_queued = 0, /* tty i/o queued in contti() */
- conch, /* console input character buffer */
- curcarr = 0, /* Carrier mode: require/ignore */
- ttch; /* tty input character buffer */
- static unsigned char escchr; /* Escape or attn character */
- static char ttnmsv[80]; /* copy of open path for tthang */
- static char lclnam[80]; /* Local device name */
-
- static char tt_fulldevnam[65];
- static struct dsc$descriptor_s tt_fulldevnam_d; /* Descriptor for line name */
-
- static long int qio_maxbuf_size; /* Maximum size of QIO to succeed */
- static unsigned long dclexh_status; /* Exit status for DCL exit handler */
- static struct iosb_struct coniosb, ttiosb, wrk_iosb;
- static struct tt_mode
- ttold, ttraw, tttvt, /* for communication line */
- ccold, ccraw, cccbrk, /* and for console */
- cctmp;
-
- /* Network support */
-
- #include "ckcnet.h" /* Network type symbols */
- extern int ttnet; /* Network type */
- static int network = 0; /* 1 if network connection */
- extern int xfrcan, xfrchr, xfrnum; /* Transfer cancellation */
-
- /* Needed for parity fixes in edit 036 */
- extern int parity; /* current parity setting */
-
- /*
- New buffered input scheme.
- */
- #define TTXBUF
-
- #ifdef TTXBUF
- #define TTXBUFL RBSIZ /* Internal buffer size */
-
- CHAR ttxbuf[TTXBUFL+1]; /* The buffer */
- int ttxbp = 0, ttxbn = 0; /* Buffer pointer and count */
-
- /*
- T X B U F R
-
- Read bytes from communication device into internal buffer ttxbuf[].
- To be called only when input buffer is empty, i.e. when ttxbn == 0.
-
- Other comm-device reading routines, like ttinc, ttinl, ttxin, should check
- the internal buffer first, and call this routine for a refill if necessary.
-
- When data is read successfully, the first character is returned and
- the global buffer count, ttxbn, is set to the number of characters remaining
- in ttxbuf after it, and the global buffer offset, ttxbp, is set to 1.
-
- When data is not read successfully, -1 is returned indicating a timeout,
- or -2 indicating disconnection.
- */
- int
- txbufr(timo) int timo; { /* TT Buffer Read */
- int count;
- int func; /* Read function code */
- int mask; /* Event mask */
- int vms_status; /* Read QIO return code */
- static int trmmsk[2] = {0,0}; /* Terminal read break mask */
- static int trmlong[8] = {0,0,0,0,0,0,0,0}; /* Break on nothing */
-
- debug(F101,"txbufr entry, ttxbn","",ttxbn);
- if (ttxbn > 0) { /* Should not be called */
- debug(F101,"txbufr called with ttxbn","",ttxbn); /* if ttxbn > 0! */
- ttxbn--;
- return(ttxbuf[ttxbp++] & 0xff);
- }
- ttxbp = ttxbn = 0; /* Reset buffer pointer and count */
- ttxbuf[0] = NUL;
-
- if (timo < 0) /* Be safe */
- timo = 0;
- debug(F101,"txbufr timo","",timo);
-
- func = IO$_READVBLK | IO$M_NOFILTR; /* Read virtual block, no filtering */
- trmmsk[0] = sizeof(trmlong); /* No terminators */
- trmmsk[1] = (int)&trmlong; /* Keep all characters */
-
- /*
- We try to scoop up as many as we can in a nonblocking read (timed, but with
- timeout value of 0). This is supposed to return immediately with up to
- "count" characters placed in our buffer.
- */
- count = TTXBUFL; /* Maximum characters to read */
-
- #ifdef COMMENT
- /*
- This causes problems because we are not adjusting according to the CURRENT
- BYTLM quota, but rather to the one that was obtained when Kermit started.
- Since the quota is dynamic, it might have been reduced since then.
- */
- if (count > qio_maxbuf_size)
- count = qio_maxbuf_size;
- #else
- /*
- So for now we use 1024, which tends to be smaller than the value obtained
- above. Later, this should be changed to find out the remaining BYTLM quota
- and use that instead. This size can be overridden at compile time by
- defining the symbol...
- */
- #ifndef CKV_IO_SIZE
- #define CKV_IO_SIZE 1024
- #endif /* CKV_IO_SIZE */
-
- if (count > CKV_IO_SIZE)
- count = CKV_IO_SIZE;
- #endif /* COMMENT */
-
- debug(F101,"txbufr 1 read","",count);
- vms_status = sys$qiow(QIOW_EFN, ttychn, func|IO$M_TIMED, &wrk_iosb, 0, 0,
- ttxbuf, count, 0, &trmmsk, 0, 0);
- /*
- * Did something _really_ bad happen?
- */
- if (vms_status != SS$_NORMAL) {
- debug(F101,"txbufr 1 serious error, status","",vms_status);
- return(-2);
- }
-
- debug(F101,"txbufr 1 size","",wrk_iosb.size);
- debug(F101,"txbufr 1 iosb","",wrk_iosb.status);
- debug(F110,"txbufr 1 ttxbuf",ttxbuf,0);
-
- /*
- * How about a hangup?
- */
- if (wrk_iosb.status == SS$_HANGUP) { /* Check for disconnection */
- debug(F100,"txbufr 1 hangup","",0);
- return(-2);
- }
-
- /*
- * Did anything useful happen?
- */
- if(wrk_iosb.size > 0) {
- ttxbn = wrk_iosb.size; /* Set buffer count. */
- ttxbn--; /* Less one for the one we return */
- return(ttxbuf[ttxbp++] & 0xff); /* Return it, bump offset */
- }
-
- /*
- * An unexpected status?
- */
- if (wrk_iosb.status != SS$_TIMEOUT) {
- debug(F101, "txbufr 1 unexpected iosb status", "", wrk_iosb.status);
- return(-2); /* Call it a hangup */
- }
-
- /*
- * If we didn't get any characters, then try a blocking, possibly timed,
- * read for a single character. Since this routine will called again very
- * soon, the first read with a zero timeout will have the rest of the user
- * data in it. Thus, this isn't as inefficient as it first appears.
- */
- if (timo > 0) func |= IO$M_TIMED;
- debug(F101,"txbufr 2 read","",count);
- vms_status = sys$qiow(QIOW_EFN, ttychn, func, &wrk_iosb, 0, 0,
- ttxbuf, 1, timo, &trmmsk, 0, 0);
- /*
- * Did something _really_ bad happen?
- */
- if (vms_status != SS$_NORMAL) {
- debug(F101,"txbufr 2 serious error, status","",vms_status);
- return(-2);
- }
-
- debug(F101,"txbufr 2 size","",wrk_iosb.size);
- debug(F101,"txbufr 2 iosb","",wrk_iosb.status);
- debug(F110,"txbufr 2 ttxbuf",ttxbuf,0);
-
- /*
- * How about a hangup?
- */
- if (wrk_iosb.status == SS$_HANGUP) { /* Check for disconnection */
- debug(F100,"txbufr 2 hangup","",0);
- return(-2);
- }
-
- /*
- * Did anything useful happen?
- */
- if(wrk_iosb.size > 0) {
- ttxbn = wrk_iosb.size; /* Set buffer count. */
- ttxbn--; /* Less one for the one we return */
- return(ttxbuf[ttxbp++] & 0xff); /* Return it, bump offset */
- }
-
- /*
- * An unexpected status?
- */
- if (wrk_iosb.status != SS$_TIMEOUT) {
- debug(F101, "txbufr 2 unexpected iosb status", "", wrk_iosb.status);
- return(-2); /* Call it a hangup */
- }
-
- /*
- * Otherwise it's a timeout
- */
- debug(F101, "txbufr 2 returning timeout", "", 0);
- return(-1);
- }
-
- /* T T I N C -- Read a character from the communication device */
- /*
- ttinc() maintains an internal buffer to minimize system calls.
- Returns the next character, or -1 if there is a timeout, or -2
- on communications disconnect. Calls txbufr() to refill its buffer
- when necessary.
- */
- int
- ttinc(timo) int timo; {
- int x; unsigned char c;
-
- #ifdef NETCONN
- if (network)
- return(netinc(timo));
- #endif /* NETCONN */
-
- debug(F101,"ttinc ttxbn","",ttxbn);
- if (--ttxbn >= 0) { /* Something in internal buffer? */
- c = ttxbuf[ttxbp++]; /* Yes, return next character. */
- debug(F101,"ttinc returns c","",c);
- return(c & 0xff);
- } else if ((x = txbufr(timo)) < 0) { /* No, fill buffer */
- debug(F101,"ttinc timed out","",x); /* Pass along failure. */
- return(x);
- } else { /* Success. */
- debug(F101,"ttinc returns x","",x);
- return(x & 0xff); /* Return the character */
- }
- }
-
- /* T T X I N -- Get n bytes from tty input buffer */
- /*
- Call with n = number of bytes to get, buf = where to put them.
-
- This routine assumes that the given number of bytes is available
- and will not return until they are gotten. You should only call this
- routine after calling ttchk to find out how many bytes are waiting to
- to be read.
-
- Returns:
- -1 on error, number of chars gotten on success.
- */
- int
- ttxin(n,buf) int n; CHAR *buf; {
- int i, x;
-
- debug(F101,"ttxin","",n);
-
- #ifdef NETCONN
- if (network) {
- for (i = 0; i < n; i++) {
- if ((x = ttinc(0)) < 0) return(-1);
- buf[i] = (char) x;
- }
- } else {
- #endif /* NETCONN */
- /* xx_inc() is a macro */
- for (i = 0; i < n; i++) {
- if ((x = xx_inc(0)) < 0) return(-1);
- buf[i] = (char) x;
- }
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- buf[i] = NUL;
- return(i);
- }
-
- /* T T F L U I -- Flush communication device input buffer */
-
- int
- ttflui() {
- int n;
- debug(F100,"ttflui","",0);
- #ifdef NETCONN
- if (network)
- return(netflui());
- #endif /* NETCONN */
-
- ttxbn = ttxbp = 0; /* Flush internal buffer *FIRST* */
- if ((n = ttchk()) > 0) {
- debug(F101,"ttflui count","",n);
- #ifdef NETCONN
- if (network)
- while ((n--) && ttinc(2) > -1) ; /* Don't worry, it's buffered. */
- else
- #endif /* NETCONN */
- while ((n--) && xx_inc(2) > -1) ; /* Don't worry, it's buffered. */
- }
- return(0);
- }
-
- /* T T C H K -- Check how many bytes are waiting to be read */
- /*
- Returns number of bytes waiting, or -1 if connection has been dropped.
- The number of bytes waiting includes those in our internal buffer plus
- those in VMS's internal input buffer.
- */
- int /* Check how many bytes are ready */
- ttchk() { /* for reading from network */
- static struct {
- unsigned short count;
- unsigned char first;
- unsigned char reserved1;
- long reserved2; } ttchk_struct;
-
- #ifdef NETCONN
- if (network) /* If network connection active... */
- return(nettchk()); /* Check real network. */
- #endif /* NETCONN */
-
- CHECK_ERR("ttchk: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_SENSEMODE|IO$M_TYPEAHDCNT, &wrk_iosb,
- 0, 0, &ttchk_struct, sizeof(ttchk_struct), 0, 0, 0, 0));
- #ifdef DEBUG
- debug(F101,"ttchk count","",(int)ttchk_struct.count);
- if (ttchk_struct.count)
- debug(F101,"ttchk first","",(int)ttchk_struct.first);
- #endif /* DEBUG */
- return(vms_status & 1 ? ttchk_struct.count + ttxbn : ttxbn);
- }
-
- #ifdef CTRLC
- #undef CTRLC
- #endif /* CTRLC */
- #define CTRLC '\03'
-
- /* T T I N L -- Read a record (up to break character) from comm line. */
- /*
- Reads up to "max" characters from the communication line, terminating on:
-
- (a) the packet length field if the "turn" argument is zero, or
- (b) on the packet-end character (eol) if the "turn" argument is nonzero
- (c) two Ctrl-C's in a row
-
- and returns the number of characters read upon success, or if "max" was
- exceeded or the timeout interval expired before (a) or (b), returns -1.
-
- The characters that were input are copied into "dest" with their parity bits
- stripped if parity was selected. Returns the number of characters read.
- Characters after the eol are available upon the next call to this function.
-
- Since this function has grown to have its fingers so deeply into the
- protocol, it is slated for removal: rpack() will take care of everything.
- */
-
- int
- #ifdef CK_ANSIC
- ttinl(CHAR *dest, int max, int timo, CHAR eol, CHAR start, int turn)
- #else
- ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest,eol,start;
- #endif /* CK_ANSIC */
- /* ttinl */ {
- int x, y, c, i, j;
- int ccn = 0; /* Control C counter */
- int flag;
- int cc;
- unsigned char *cp;
- int pktlen = -1;
- int lplen = 0;
- int havelen = 0;
-
- debug(F101,"ttinl start","",start);
- debug(F101,"ttinl turn","",turn);
- i = j = flag = 0;
- ttpmsk = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */
- while (i < max) {
- cc = network ? ttinc(timo) : xx_inc(timo); /* Read a byte */
- if (cc < 0) /* Check for error */
- return(-1);
- if (xfrcan && ((cc & 0x7f) == xfrchr)) { /* Check for cancellation */
- if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
- fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */
- return(-2);
- }
- } else ccn = 0; /* No cancel, so reset counter, */
-
- if ((flag == 0) && ((cc & 0x7f) == start)) {
- debug(F100,"ttinl got start","",0);
- flag = 1; /* Got packet start. */
- }
- if (flag) { /* If we're in a packet... */
- dest[i++] = cc & ttpmsk;
- if ((cc & 0x7f) == eol) { /* Stop at eol. */
- debug(F101,"ttinl got eol, i","",i);
- break;
- }
- }
- /*
- If we have not been instructed to wait for a turnaround character, we
- can go by the packet length field. If turn != 0, we must wait for the
- end of line (eol) character before returning.
- */
- #ifndef xunchar
- #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
- #endif /* xunchar */
-
- if (i == 2) {
- pktlen = xunchar(dest[1]);
- havelen = (pktlen > 1);
- debug(F101,"ttinl length","",pktlen);
- } else if (i == 5 && pktlen == 0) {
- lplen = xunchar(dest[4]);
- } else if (i == 6 && pktlen == 0) {
- pktlen = lplen * 95 + xunchar(dest[5]) + 5;
- havelen = 1;
- debug(F101,"ttinl length","",pktlen);
- }
- if (havelen && !turn && (i > pktlen+1)) { /* Use length field */
- debug(F101,"ttinl break on length","",i);
- break;
- }
- }
- dest[i] = '\0'; /* Terminate the string */
- debug(F101,"ttinl loop done, i","",i);
- debug(F101,"ttinl max","",max);
- debug(F101,"ttinl dest[i-1]","",dest[i-1]);
- debug(F101,"ttinl eol","",eol);
-
- if (i >= max) {
- debug(F100,"ttinl buffer overflow","",0);
- return(-1); /* Overflowed dest buffer without getting eol */
- }
- x = i; /* Size. */
- debug(F111,"ttinl got packet",dest,x);
-
- debug(F101,"ttinl size","",x); /* Log the size */
- dest[x] = '\0'; /* Terminate with null */
-
- if (ttpflg++ == 0 && ttprty == 0) { /* Check and adjust the parity. */
- if ((ttprty = parchk(dest,start,x)) > 0) {
- debug(F000,"ttinl parchk senses parity","",ttprty);
- ttpmsk = 0x7f;
- for (i = 0; i < x; i++) /* Strip parity from this packet */
- dest[i] &= 0x7f;
- }
- if (ttprty < 0) ttprty = 0; /* Restore if parchk error */
- }
- return(x); /* Return length */
- }
-
- #endif /* TTXBUF */
-
- SIGTYP (*saval)() = NULL; /* For saving alarm handler */
-
- VOID
- ttimoff() { /* Turn off any timer interrupts */
- alarm(0);
- if (saval)
- signal(SIGALRM,saval);
- else
- signal(SIGALRM,SIG_DFL);
- saval = NULL;
- }
-
- /* P R I N T _ M S G -- Log an error message from VMS */
-
- int
- print_msg(s) char *s; {
- long int blen = 0;
- char buf[PMSG_BUF_SIZE], msg[PMSG_MSG_SIZE];
- struct dsc$descriptor_s b = {
- PMSG_BUF_SIZE-1,
- DSC$K_DTYPE_T,
- DSC$K_CLASS_S,(char *)&buf
- };
-
- if (!((vms_status = sys$getmsg(vms_status, &blen, &b, 0, 0)) & 1)) {
- fprintf(stderr,"print_msg; sys$getmsg\n");
- return(-1);
- }
- buf[blen] = '\0';
- sprintf(msg, "%s: %s\n", s, buf);
- debug(F100,s,"",0);
- ermsg(msg);
- return(0);
- }
-
- /* S Y S I N I T -- System-dependent program initialization. */
-
- #ifndef DVI$_FULLDEVNAM
- #define DVI$_FULLDEVNAM 232
- #endif /* DVI$_FULLDEVNAM */
-
- #ifndef DVI$_STS
- #define DVI$_STS 226
- #endif /* DVI$_STS */
-
- int
- sysinit() {
- extern int speed;
- extern char ttname[];
- extern char *ckzsys;
- struct itmlst dviitm[] = {{64,DVI$_FULLDEVNAM,(char *)&lclnam,0},
- {sizeof(conclass),DVI$_DEVCLASS,(char *)&conclass,0},
- {0,0,0,0}};
-
- static struct desblk {
- long int *fl; /* Forward link. Used by VMS only */
- void (*fncpnt)(); /* Function to call */
- unsigned char argcnt; /* Only one arg allowed */
- unsigned char filler[3]; /* Filler. Must be zero */
- long int *sts; /* Address of sts (written by VMS) */
- } dclexh_ = {0,dcl_exit_h,1,{0,0,0},&dclexh_status};
-
- #define GETCKXSYS
- /*
- Get architecture and operating system name.
- */
- #ifdef GETCKXSYS
-
- #if defined(__ALPHA)
-
- ckxsys = " OpenVMS AXP";
-
- #elif !(defined(__VAX) || defined (VAX) || defined (__GNUC__))
- # error Unknown Hardware type, not VAX(tm) and not AXP (TM)
- #else /* VAX */
-
- /* OK, we have a VAX so what is the name of the OS? */
-
- #ifndef SYI$_ARCH_NAME /* Should be in syidef.h but is not there yet */
- # define SYI$_ARCH_NAME 4454
- #endif /* SYI$_ARCH_NAME */
-
- struct iosb_t {
- short int status; /* System service status */
- short int unused[3];
- } iosb;
-
- struct itmlst_t {
- short unsigned int buffer_len; /* Buffer length */
- short unsigned int item_code; /* Item code */
- char*buffer; /* Where to write SYI info */
- long unsigned int *ret_len; /* Pointer to returned length */
- long unsigned int mbz; /* Must Be Zero */
-
- } itmlst;
-
- char arch_name[sizeof ("Alpha") - 1]; /* Architecture name */
- long unsigned int ret_len; /* Returned length */
- /*
- $getsyi of "hw_arch" will fail prior to VMS 5.5. This failure indicates that
- the OS name is "VAX/VMS" (sic). Use success or failure or $getsyi "hw_arch"
- rather than the more straight forward $getsyi "node_swvers" because latter
- is defined as four (4) characters and will get strange representing VMS
- 10.0.
- */
-
- /* Default -- Not strictly correct but traditional & familiar... */
- ckxsys = " VAX/VMS";
-
- itmlst.buffer_len = sizeof (arch_name);
- itmlst.item_code = SYI$_ARCH_NAME;
- itmlst.buffer = arch_name;
- itmlst.ret_len = &ret_len;
- itmlst.mbz = 0;
-
- if ((sys$getsyiw (0, 0, 0,
- &itmlst,
- &iosb,
- 0, 0) & 1) == 1)
- if ((iosb.status & 1) == 1)
- ckxsys = " OpenVMS VAX";
-
- ckzsys = ckxsys; /* Same deal for file module */
-
- #endif /* OS Type */
- #endif /* GETCKXSYS */
-
- /*
- * Set up DCL Exit handler. This allows us to reset terminal
- * and any other modifications we have done.
- */
- debug(F101,"sysinit ttychn","",ttychn);
- debug(F101,"sysinit conchn","",conchn);
- if (!CHECK_ERR("sysinit: sys$dclexh",
- sys$dclexh(&dclexh_))) {
- debug(F100,"sysinit failed to declare exit handler","",0);
- #ifdef COMMENT
- return(0);
- #endif /* COMMENT */
- }
- if (ttychn) /* if comms line already opened */
- return(0); /* (how could it be???) */
-
- if (!conchn) { /* Get console channel */
- struct dsc$descriptor_s devnam =
- {sizeof(dftty)-1,DSC$K_DTYPE_T,DSC$K_CLASS_S,dftty};
- conchn = vms_assign_channel(&devnam);
- }
- congm(); /* Get and save its modes */
- /*
- * Parse console terminal device name.
- */
- CHECK_ERR("sysinit: sys$getdviw",
- sys$getdviw(0, conchn, 0, &dviitm, &wrk_iosb, 0, 0, 0));
- debug(F111,"sysinit","lclnam",lclnam);
-
- if (!CHECK_ERR("sysinit: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SENSEMODE, &wrk_iosb, 0, 0,
- &ccold, sizeof(ccold), 0, 0, 0, 0))) return(-1);
-
- speed = ttispd((unsigned char) wrk_iosb.size);
- debug(F111,"sysinit speed",lclnam,speed);
- strncpy(ttname,lclnam,80);
-
- /* Initialize descriptor */
- tt_fulldevnam_d.dsc$b_dtype = DSC$K_DTYPE_T;
- tt_fulldevnam_d.dsc$b_class = DSC$K_CLASS_S;
-
- debug(F100,"sysinit done","",0);
- return(0);
- }
-
- /*
- * DCL Exit handler. This is the cleanup handler for program.
- * Any final cleanup (closing channels etc) should be done at this
- * point.
- */
- VOID
- dcl_exit_h(sts) unsigned long int *sts; {
- syscleanup();
- return;
- }
-
- /* S Y S C L E A NU P -- System-dependent program epilog. */
-
- int
- syscleanup() {
- extern zclosf();
-
- ttclos(ttyfd); /* Do the cleanup no matter what... */
- conres(); /* for the console also... */
- zclosf(); /* Close various files and kill child proc */
- printf("\r");
- return(0);
- }
-
- /* T T O P E N -- Open a tty for exclusive access. */
-
- /* Returns 0 on success, -1 on failure. */
- /*
- If called with lcl < 0, sets value of lcl as follows:
- 0: the terminal named by ttname is the job's controlling terminal.
- 1: the terminal named by ttname is not the job's controlling terminal.
- But watch out: if a line is already open, or if requested line can't
- be opened, then lcl remains (and is returned as) -1.
- */
- int
- ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
- extern int speed;
- int s;
- unsigned long int devchar, devclass, devsts;
- /* char dvibuf[65]; */
- struct dsc$descriptor_s devnam = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
- struct itmlst dviitm[] = {{64,DVI$_FULLDEVNAM,(char *)&tt_fulldevnam,0},
- {sizeof(devchar),DVI$_DEVCHAR,(char *)&devchar,0},
- {sizeof(devclass),DVI$_DEVCLASS,(char *)&devclass,0},
- {sizeof(devsts),DVI$_STS,(char *)&devsts,0},
- {0,0,0,0}};
-
- #ifdef NETCONN
- if (network && ttyfd > -1) { /* if device already opened */
- if (strncmp(ttname,ttnmsv,80)) /* are new & old names equal? */
- ttclos(ttyfd); /* no, close old ttname, open new */
- else /* else same, ignore this call, */
- return(0); /* and return. */
- }
- if (modem < 0) { /* modem < 0 = special code for net */
- int x;
- ttmdm = modem;
- modem = -modem; /* Positive network type number */
- debug(F111,"ttopen net",ttname,modem);
- x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
- if (x > -1) {
- strncpy(ttnmsv,ttname,DEVNAMLEN);
- network = 1;
- x = tn_ini(); /* Initialize telnet protocol. */
- ttnet = modem;
- } else network = 0;
- return(x);
- }
- #endif /* NETCONN */
-
- if (ttychn) return(0); /* Close channel if open */
-
- devnam.dsc$w_length = strlen(ttname);
- devnam.dsc$a_pointer = ttname;
- sys$getdviw(0, 0, &devnam, &dviitm, &wrk_iosb, 0, 0, 0);
- tt_fulldevnam[65] = '\0'; /* Make sure it has an end.... */
-
- if (devclass != DC$_TERM) { /* Is it a terminal? */
- fprintf(stderr,
- "%%CKERMIT-W-NOTTERM, %s is not a terminal\n",ttname);
- return(-1);
- }
- if (!(devchar & DEV$M_AVL)) { /* Is it available? */
- fprintf(stderr,
- "%%CKERMIT-W-NOTAVAL, %s is not available\n",tt_fulldevnam);
- return(-5);
- }
- if (!(devsts & UCB$M_ONLINE)) { /* Is it online? */
- fprintf(stderr,
- "%%CKERMIT-W-OFFLINE, %s is not online\n",tt_fulldevnam);
- return(-5);
- }
- ttmdm = modem; /* Make this available to other fns */
- xlocal = *lcl; /* Make this available to other fns */
-
- /*
- * Set up the tt_fulldevnam_d descriptor for use by ttclos() later.
- */
- tt_fulldevnam_d.dsc$w_length = strlen(tt_fulldevnam);
- tt_fulldevnam_d.dsc$a_pointer = tt_fulldevnam;
-
- /*
- * Try to allocate the device. This is necessary to avoid just assigning
- * a channel with SHARE privilege and interfering with someone else using
- * the terminal.
- */
- if (!CHECK_ERR("vms_allocate_device: sys$alloc",
- sys$alloc(&tt_fulldevnam_d, 0, 0, 0, 0))) return(-1);
-
- ttychn = vms_assign_channel(&devnam); /* Get a channel for it. */
-
- debug(F111,"ttopen","modem",modem);
- debug(F101," ttychn","",ttychn);
-
- if (!ttychn) return(-1); /* If couldn't open, fail. */
- /*
- * Check for maximum size of QIO, so as to not get the dreaded quota exceeded
- * status returned. When doing a QIO that has a larger buffer than
- * MAXBUF, exceeded quota wil be returned.
- *
- * Example: MAXBUF = 2048, QIO = 1936, overhead is 112 will succeed.
- * QIO of 1937 will fail.
- *
- * This can change for different versions of VMS.
- */
- qio_maxbuf_size = get_qio_maxbuf_size(ttychn);
-
- strncpy(ttname,tt_fulldevnam,80); /* Copy true name back to main pgm */
-
- strcpy(ttnmsv,ttname); /* Open, keep copy of name locally. */
- ttxbn = ttxbp = 0; /* Initialize input buffer */
-
- /* Caller wants us to figure out if line is controlling tty */
-
- debug(F111,"ttopen ok",ttname,*lcl);
- if (*lcl < 0) {
- if (conclass == DC$_TERM)
- xlocal = (strncmp(ttname,lclnam,80) == 0) ? 0 : 1;
- else
- xlocal = 1; /* If not a term, then we must be local */
- debug(F111,"ttyname",lclnam,xlocal);
- }
- if (!CHECK_ERR("ttopen: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_SENSEMODE, &wrk_iosb, 0, 0,
- &ttold, sizeof(ttold), 0, 0, 0, 0))) return(-1);
-
- speed = ttispd((unsigned char) wrk_iosb.size);
-
- /* Got the line, now set the desired value for local. */
-
- if (*lcl) *lcl = xlocal;
-
- tttvt = ttold;
- ttraw = ttold;
- debug(F101," lcl","",*lcl);
- return(0);
- }
-
- #ifdef COMMENT
- /*
- Old version.
- */
- unsigned long int
- vms_assign_channel(ttname) char *ttname; {
- unsigned int channel = 0;
- struct dsc$descriptor_s d = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
-
- d.dsc$w_length = strlen(ttname);
- d.dsc$a_pointer = ttname;
- if (!CHECK_ERR("vms_assign_channel: sys$assign",
- sys$assign(&d, &channel, 0, 0))) return(0);
- return(channel);
- }
- #else
- /*
- New version from Hunter Goatley.
- */
- unsigned long int
- vms_assign_channel(ttname) char *ttname; {
- unsigned int channel = 0;
- /*
- struct dsc$descriptor_s d = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
- d.dsc$w_length = strlen(ttname);
- d.dsc$a_pointer = ttname;
- */
- if (!CHECK_ERR("vms_assign_channel: sys$assign",
- sys$assign(ttname, &channel, 0, 0))) return(0);
- return(channel);
- }
- #endif /* COMMENT */
-
- /* T T C L O S -- Close the communication device. */
-
- int
- ttclos(ttyfd) int ttyfd; {
- #ifdef NETCONN
- if (network) { /* Network connection. */
- debug(F100,"ttclos closing net","",0);
- netclos(); /* Close it. */
- network = 0;
- return(0);
- }
- #endif /* NETCONN */
- if (!ttychn) return(0); /* Wasn't open. */
- /*
- Observations indicate that it can take 20-30 seconds for DTR to drop
- after closing the device. Perhaps a call to tthang() should go here.
- */
- ttres(); /* Reset modes. */
-
- /*
- Assume it's a LAT device and try to do a LAT disconnect on it.
- If it fails, then it's not a LAT device and no harm is done.
- */
- #ifdef IO$M_LT_DISCON
- vms_status = sys$qiow(QIOW_EFN, ttychn, IO$_TTY_PORT|IO$M_LT_DISCON,
- &wrk_iosb, 0, 0, 0, 0, 0, 0, 0, 0);
- debug(F101, "ttclos LAT disconnect, status", "", vms_status);
- debug(F101, "ttclos LAT disconnect, iosb", "", wrk_iosb.status);
- #else
- debug(F100, "ttclos LAT disconnect not supported", "", 0);
- #endif /* IO$M_LT_DISCON */
- if (!CHECK_ERR("ttclos: sys$dassgn",
- sys$dassgn(ttychn))) return(-1);
- sys$dalloc (&tt_fulldevnam_d, 0); /* Deallocate the device */
- ttychn = 0; /* Mark it as closed. */
- return(0);
- }
-
-
- /* T T R E S -- Restore terminal to its original modes. */
-
- int
- ttres() { /* Restore the tty to normal. */
- #ifdef NETCONN
- if (network) return (0); /* Network connection, do nothing */
- #endif /* NETCONN */
-
- if (!ttychn) return(-1); /* Not open. */
-
- tt_cancel(); /* Cancel outstanding I/O */
- msleep(250); /* Wait for pending i/o to finish. */
- debug(F101,"ttres, ttychn","",ttychn);
- if (!CHECK_ERR("ttres: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ttold, sizeof(ttold), 0, 0, 0, 0))) return(-1);
- return(0);
- }
-
- /* T T B I N -- Code shared by ttpkt() and ttvt() */
- /*
- Puts communication device in "binary" mode. In VMS there's no distinction
- between device modes for terminal connection, packet operation, and dialing.
- */
- static int
- ttbin(speed, xflow, xparity) int speed, xflow, xparity; {
- int s;
- extern int flow; /* Global flow control variable */
-
- #ifdef NETCONN
- if (network) return(0); /* Nothing to do on net connections */
- #endif /* NETCONN */
- if (!ttychn) return(-1); /* Not open. */
-
- ttspeed = speed; /* Keep local copies of arguments */
- if (xflow != FLO_DIAL && ttflow != FLO_DIAX)
- ttflow = xflow; /* for other CKVTIO routines. */
- if (xparity > -1) {
- ttprty = xparity;
- ttpflg = 0; /* Parity not sensed yet */
- ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
- debug(F101,"ttbin ttprty","",ttprty);
- }
- ttraw = ttold; /* Get a fresh copy of this */
-
- if ((s = ttsspd(speed/10)) < 0) /* Get internal speed code */
- s = 0;
-
- /*
- * Log original terminal settings for debugging purposes
- */
- debug(F101, "original ttraw.basic", "", ttraw.basic);
- debug(F101, "original ttraw.extended", "", ttraw.extended);
-
- /*
- * Settings based on call parameters flow-control and parity...
- * NOTE: we are using the GLOBAL copy of flow, not our parameter here.
- * This is because the parameter might be FLO_DIAL or FLO_DIALX, which
- * is not flow control at all.
- */
- if (flow == FLO_XONX) { /* FLOW = XON/XOFF */
- ttraw.basic |= (TT$M_HOSTSYNC|TT$M_TTSYNC);
- } else if (flow == FLO_NONE) { /* FLOW = NONE */
- ttraw.basic &= ~(TT$M_HOSTSYNC|TT$M_TTSYNC);
- } else if (flow == FLO_KEEP) { /* FLOW = KEEP */
- /*
- * Put flow-control paramaters back the way we found them when
- * the device was first opened.
- */
- if (ttold.basic & TT$M_HOSTSYNC)
- ttraw.basic |= TT$M_HOSTSYNC;
- else
- ttraw.basic &= ~TT$M_HOSTSYNC;
- if (ttold.basic & TT$M_TTSYNC)
- ttraw.basic |= TT$M_TTSYNC;
- else
- ttraw.basic &= ~TT$M_TTSYNC;
- /*
- NOTE: any other FLOW-related parameters should also be handled here.
- READSYNC? And especially if DEC ever implements RTS/CTS or other
- hardware flow control for (Open)VMS.
- */
- }
-
- /*
- EIGHTBIT setting depends on GLOBAL copy of parity variable, not our
- parameter.
- */
- if (parity == 0)
- ttraw.basic |= TT$M_EIGHTBIT; /* Allow 8-bit data if no parity */
- else /* Otherwise */
- ttraw.basic &= ~TT$M_EIGHTBIT; /* 7-bit data. */
-
- ttraw.basic |= TT$M_NOECHO; /* Turn off echo */
- ttraw.basic |= TT$M_NOBRDCST; /* Turn off broadcasts */
- ttraw.basic &= ~TT$M_NOTYPEAHD; /* Enable type-ahead */
- ttraw.basic &= ~TT$M_ESCAPE; /* Disable escape-seq processing */
- ttraw.extended &= ~TT2$M_LOCALECHO; /* Disable local echo */
- ttraw.extended |= TT2$M_PASTHRU; /* Enable pass-through mode */
- ttraw.extended |= TT2$M_ALTYPEAHD; /* Use big type-ahead buffers */
-
- /*
- * Report what we did so we can check for problems
- */
- debug(F101, "ttraw.basic", "", ttraw.basic);
- debug(F101, "ttraw.extended", "", ttraw.extended);
-
- vms_status = sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ttraw, sizeof(ttraw), s, 0, 0, 0);
-
- if (vms_status != SS$_NORMAL) { /* Error queuing request */
- print_msg("ttbin: sys$qiow");
- return(-1);
- }
- if (wrk_iosb.status != SS$_NORMAL) { /* Error executing request */
- vms_status = wrk_iosb.status;
- print_msg("ttbin: sys$qiow(iosb)");
- return(-1);
- }
- debug(F100,"ttbin ok","",0);
- return(0); /* All OK */
- }
-
- /* T T P K T -- Condition the communication device for packets. */
-
- #ifdef COMMENT
- #define DIALING 4 /* Flags (via flow) for modem handling */
- #define CONNECT 5 /* NOT YET IMPLEMENTED IN VMS! */
- #endif /* COMMENT */
-
- /* Returns 0 on success, -1 on failure. */
-
- int
- ttpkt(speed,flow,parity) long speed; int flow, parity; {
- int x;
- debug(F101,"ttpkt flow","",flow);
- x = ttbin(speed,flow,parity); /* Put device in binary mode */
- debug(F101,"ttpkt ttbin","",x);
- return(x);
- }
-
- /* T T V T -- Condition communication device terminal connection. */
-
- int
- ttvt(speed,flow) long speed; int flow; {
- int x;
- debug(F101,"ttvt flow","",flow);
- if ((x = ttbin(speed,flow,-1)) > -1) /* Put device in binary mode */
- tvtflg = 1;
- debug(F101,"ttvt ttbin","",x);
- return(x);
- }
-
- /* T T I S P D -- Return binary baud rate for internal coded speed */
-
- int
- ttispd(ispeed) unsigned char ispeed; {
- int s;
-
- #ifdef NETCONN
- if (network) return(-1);
- #endif /* NETCONN */
-
- /* When the line is set, grab the line speed and save it */
-
- for (s = 0; ttspeeds[s].dec &&
- (ttspeeds[s].dec != ispeed); s++)
- ;
-
- /* If speed is zero, then no match. Set speed to -1 so it is undefined */
-
- return(ttspeeds[s].line ? (int) ttspeeds[s].line * 10 : -1);
-
- }
-
-
- /* T T S S P D -- Return the internal baud rate code for 'speed'. */
-
- int
- ttsspd(cps) int cps; {
- int s;
- char msg[50];
-
- #ifdef NETCONN
- if (network) return(0);
- #endif /* NETCONN */
-
- if (cps <= 0) /* 026 Unknown cps fails */
- return (-1);
- for (s = 0; ttspeeds[s].line && (ttspeeds[s].line != cps); s++) ;
- if (ttspeeds[s].line)
- return(ttspeeds[s].dec);
- else {
- sprintf(msg,"Unsupported line speed - %d\n",cps*10);
- ermsg(msg);
- ermsg("Current speed not changed\n");
- return(-1);
- }
- }
-
-
- /* Interrupt Functions */
-
-
- /* C O N I N T -- Console Interrupt setter */
-
- static int (*cctrap)();
-
- VOID
- #ifdef CK_ANSIC
- conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
- #else
- conint(f,s) int (*f)(int), (*s)(int);
- #endif /* CK_ANSIC */
- /* conint */ { /* Set an interrupt trap. */
-
- cctrap = f; /* Make a global copy */
- debug(F101,"conint batch","",batch);
- if (batch) return; /* Ignore signals in background. */
-
- /* check if invoked in background -- if so signals set to be ignored */
-
- #ifdef COMMENT
- /* This is interfered with by connoi() */
- if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
- debug(F100,"conint signal diagnoses batch","",0);
- batch = 1; /* means running in background */
- return;
- }
- #else
- if (!isatty(0)) {
- debug(F100,"conint isatty diagnoses batch","",0);
- batch = backgrd = 1; /* means running in background */
- return;
- }
- #endif /* COMMENT */
-
- signal(SIGINT,f); /* Function to trap to. */
- conif = 1; /* Flag console interrupts on. */
- }
-
- /* C O N N O I -- Reset console terminal interrupts */
-
- VOID
- connoi() { /* Console-no-interrupts */
-
- if (batch) return; /* must ignore signals in bkgrd */
-
- #ifdef COMMENT
- /* wrong... */
- signal(SIGINT,SIG_DFL);
- #else
- /* right?.. */
- signal(SIGINT,SIG_IGN);
- #endif /* COMMENT */
- conif = 0;
- }
-
- /* T T O L -- Similar to "ttinl", but for writing. */
- /*
- * This probably should be buffered with a flush command added.
- */
-
- #ifndef IO$M_BREAKTHRU
- #define IO$M_BREAKTHRU 0x0200
- #endif /* IO$M_BREAKTHRU */
-
- int
- ttol(s,n) int n; CHAR *s; {
- int x;
-
- #ifdef NETCONN
- debug(F101,"ttol network","",network);
- if (network) {
- x = nettol(s,n); /* Call network package. */
- } else {
- #endif /* NETCONN */
- debug(F101,"ttol ttychn","",ttychn);
- if (!ttychn) return(-1); /* Not open. */
- if (CHECK_ERR("ttol: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_WRITEVBLK|IO$M_BREAKTHRU,
- &wrk_iosb, 0, 0, s, n, 0, 0, 0, 0)))
- x = n; /* was x = 0 */
- else x = -1;
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- debug(F111,"ttol",s,n);
- if (x < 0) debug(F101,"ttol failed","",x);
- return(x);
- }
-
- /* T T O C -- Output a character to the communication line */
-
- int
- #ifdef CK_ANSIC
- ttoc(char c)
- #else
- ttoc(c) char c;
- #endif /* CK_ANSIC */
- /* ttoc */ {
- #ifdef NETCONN
- if (network) {
- return(nettoc(c));
- } else {
- #endif /* NETCONN */
- debug(F101,"ttoc char","",c);
- if (!ttychn) {
- debug(F100,"ttoc ttychn not open","",0);
- return(-1); /* Not open. */
- }
- if (CHECK_ERR("ttoc: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_WRITEVBLK|IO$M_BREAKTHRU,
- &wrk_iosb, 0, 0, &c, 1, 0, 0, 0, 0)))
- return(0);
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- return(-1);
- }
-
- /* T T _ C A N C E L -- Cancel i/o on tty channel if not complete */
-
- VOID
- tt_cancel() {
- int mask;
- #ifdef NETCONN
- if (network) return;
- #endif /* NETCONN */
- CHECK_ERR("tt_cancel: sys$cancel",sys$cancel(ttychn));
- tt_queued = 0;
- }
-
- /* C O N _ C A N C E L -- Cancel i/o on console channel if not complete */
-
- VOID
- con_cancel() {
- int mask;
-
- CHECK_ERR("con_cancel: sys$cancel",sys$cancel(conchn));
- con_queued = 0;
- }
-
- /* S N D B R K -- Send a BREAK signal of the given length. */
-
- int
- sndbrk(msec) int msec; {
- int long x = 0;
- int brklen;
- struct iosb_struct tmp_ttiosb;
- struct tt_mode ttchr;
- #ifndef TT$M_BREAK /* For old VMS with no BREAK... */
- /*
- Note: 110 is used instead of 50, because 50 is not supported by all
- VAX serial port controllers.
- */
- #define BRKSPD = 110 /* Speed for simulating BREAK */
- #define BRKSYM = TT$C_BAUD_110; /* VMS symbol for this speed */
- #endif /* TT$M_BREAK */
-
- #ifdef NETCONN
- if (network) /* Send network BREAK */
- return(netbreak()); /* Length doesn't matter */
- #endif /* NETCONN */
-
- if (!ttychn) return(-1); /* SET LINE not done. */
- debug(F101,"sndbrk msec","",msec);
-
- tt_cancel(); /* Cancel I/O */
-
- #ifndef TT$M_BREAK /* VMS doesn't have BREAK function */
-
- /* Send the right number of NULs at BREAK-simulation speed... */
-
- brklen = ( BRKSPD * 1000 ) / ( msec * 10 ); /* Calculate number of chars */
- if (brklen > sizeof(brkarray)) brklen = sizeof(brkarray);
- debug(F101,"sndbrk speed","",BRKSPD);
- debug(F101,"sndbrk brklen","",brklen);
- if (!CHECK_ERR("ttsndb: SENSEMODE",
- sys$qiow(QIOW_EFN, ttychn, IO$_SENSEMODE, &wrk_iosb, 0, 0,
- &ttchr, sizeof(ttchr), 0, 0, 0, 0))) return(-1);
- if (!CHECK_ERR("ttsndb: SETMODE(1)",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &tmp_ttiosb, 0, 0,
- &ttchr, sizeof(ttchr), BRKSYM, 0, 0, 0))) return(-1);
- if (!CHECK_ERR("ttsndb: writing nulls",
- sys$qiow(QIOW_EFN, ttychn, IO$_WRITEVBLK|IO$M_BREAKTHRU, &tmp_ttiosb,
- 0, 0, (char *) brkarray, brklen, 0, 0, 0, 0))) return(-1);
- if (!CHECK_ERR("ttsndb: SETMODE(2)",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &tmp_ttiosb, 0, 0,
- &ttchr, sizeof(ttchr), wrk_iosb.size, 0, 0, 0))) return(-1);
- #else
- if (!CHECK_ERR("ttsndb: SENSEMODE",
- sys$qiow(QIOW_EFN, ttychn, IO$_SENSEMODE, &wrk_iosb, 0, 0,
- &ttchr, sizeof(ttchr), 0, 0, 0, 0))) return(-1);
- x = TT$M_BREAK; /* Break signal on */
- if (!CHECK_ERR("ttsndb: SETMODE(1)",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ttchr, sizeof(ttchr), 0, 0, x, 0))) return(-1);
- msleep(msec); /* Sleep requested amount of time */
- x = 0; /* Break signal off */
- if (!CHECK_ERR("ttsndb: SETMODE(2)",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ttchr, sizeof(ttchr), 0, 0, x, 0))) return(-1);
- #endif /* TT$M_BREAK */
- return(0);
- }
-
- /* T T S N D B -- Send a BREAK signal */
-
- int
- ttsndb() {
- return(sndbrk(275));
- }
-
- /* T T S N D L B -- Send a Long BREAK signal */
-
- int
- ttsndlb() {
- return(sndbrk(1500));
- }
-
- /* T T H A N G -- Hang up the communications line */
- /*
- Warning: As written, this function DOES NOT WORK on terminal server
- ports. This is a shortcoming of VMS, confirmed by the Digital Diagnostic
- Center (or whatever DDC stands for). Someone should add code here to test
- if the ttychn device is not a real terminal, and if so to handle it some
- other way, like set the speed to zero for a sec, or close and reopen the
- device.
- */
- int
- tthang() {
- if (!xlocal) return(0); /* Only on local connections. */
-
- #ifdef NETCONN
- if (network) { /* Network connection. */
- int x;
- if (netclos() < 0) return(-1); /* Close it */
- tvtflg = 0;
- x = 1;
- netopen(ttnmsv, &x, ttmdm); /* Open it again */
- return(1);
- }
- #endif /* NETCONN */
-
- if (!ttychn) return(0); /* Not open. */
-
- tt_cancel(); /* Cancel pending i/o. */
- /*
- This is NOT listed in the VMS Terminal Driver as one of the functions
- that does NOT work with LAT devices.
- */
- debug(F101,"tthang 1","",gtimer());
- if (!CHECK_ERR("tthang: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_SETMODE|IO$M_HANGUP, &wrk_iosb, 0, 0,
- 0, 0, 0, 0, 0, 0))) return(-1);
- /*
- The following 3-second sleep is required because the sys$qiow() returns
- immediately, about 2.5 seconds before VMS brings DTR back up. Without this
- sleep(), DIAL does not work at all if DIAL HANGUP is ON, and, worse,
- subsequent operations on the device can hang the Kermit process
- uninterruptibly.
- */
- sleep(3);
- debug(F101,"tthang 2","",gtimer());
- return(1);
- }
-
- /* M S L E E P -- Millisecond version of sleep(). */
-
- /*
- Handles intervals up to about 7 minutes (2**32 / 10**7 seconds)
- */
- int
- msleep(m) int m; {
-
- struct time_struct {
- long int hi, lo;
- } t;
-
- if (m <= 0) return(0);
- t.hi = -10000 * m; /* Time in 100-nanosecond units */
- t.lo = -1;
- if (!CHECK_ERR("msleep: sys$schdwk",
- sys$schdwk(0, 0, &t, 0))) return(-1);
- sys$hiber();
- debug(F101,"msleep ok","",m);
- return(0);
- }
-
- /* R T I M E R -- Reset elapsed time counter */
-
- VOID
- rtimer() {
- tcount = time( (long *) 0);
- }
-
-
- /* G T I M E R -- Get current value of elapsed time counter in seconds */
-
- int
- gtimer() {
- int x;
- x = (int) (time( (long *) 0 ) - tcount);
- return( (x < 0) ? 0 : x );
- }
-
- /* Z T I M E -- Return date/time string */
-
- VOID
- ztime(s) char **s; {
- static long clock;
- #ifdef COMMENT
- #ifdef bogus
- static char time_string[24];
- struct dsc$descriptor_s t =
- {sizeof(time_string)-1,DSC$K_DTYPE_T,DSC$K_CLASS_S,&time_string};
-
- if (!CHECK_ERR("ztime: sys$asctim",
- sys$asctim(0, &t, 0, 0))) return(-1);
- time_string[t.dsc$w_length] = '\0';
- *s = &time_string;
- #else
- char *asctime();
- struct tm *tp;
-
- time(&clock);
- tp = localtime(&clock);
- *s = asctime(tp);
- #endif /* bogus */
- #else /* not COMMENT */
- /*
- Apparently ctime() is available in old C libraries, even though asctime()
- is not. Let's use the same method for all versions.
- */
- time(&clock);
- *s = ctime(&clock);
- #endif /* COMMENT */
- }
-
- /* C O N G M -- Get console terminal modes. */
-
- /*
- Saves current console mode, and establishes variables for switching between
- current (presumably normal) mode and other modes.
- */
- int
- congm() {
- char s[] = "SYS$INPUT:";
- struct itmlst dviitm[] = { {4,DVI$_DEVCLASS,(char *)&dviitm[0].adr,0},
- {0,0,0,0}};
- struct dsc$descriptor_s
- r = {sizeof(s),DSC$K_DTYPE_T,DSC$K_CLASS_S,(char *)&s};
-
- debug(F101,"congm cgmf","",cgmf);
- if (cgmf) return(-1); /* If called already, then nop */
-
- if (!CHECK_ERR("congm: sys$getdviw",
- sys$getdviw(0, 0, &r, &dviitm, &wrk_iosb, 0, 0, 0))) return(-1);
- debug(F101, "congm: devclass", "", (unsigned long int) dviitm[0].adr);
- if ((unsigned long int) dviitm[0].adr != DC$_TERM)
- batch = backgrd = 1;
- else {
- debug(F101, "congm: conchn", "", conchn);
- if (conchn == 0 && (conchn = vms_assign_channel("SYS$INPUT:")) == 0)
- return(-1);
- if (!CHECK_ERR("congm: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SENSEMODE, &wrk_iosb, 0, 0,
- &ccold, sizeof(ccold), 0, 0, 0, 0))) return(-1);
- ccraw = cccbrk = ccold;
- }
- cgmf = 1; /* Flag that we got them. */
- return(0);
- }
-
- /* C O N C B -- Put console in cbreak mode. */
-
- /* Returns 0 if ok, -1 if not */
-
- int
- #ifdef CK_ANSIC
- concb(char esc)
- #else
- concb(esc) char esc;
- #endif /* CK_ANSIC */
- /* concb */ {
- int x;
-
- debug(F101,"concb batch","",batch);
- if (batch) return(0);
- if (!cgmf) congm(); /* Get modes if necessary. */
- escchr = esc; /* Make this available to other fns */
- ckxech = 1; /* Program can echo characters */
- /*
- Note: PASTHRU / PASSALL is what is preventing the Ctrl-C trap in the
- main program from working. This business can be removed without any effect
- at all on the command parser -- everything still works: completion, ?-help,
- editing, etc. The only problem is that Ctrl-Y is not trapped, so the
- program dies and leaves the terminal in no-echo mode.
- */
- cccbrk.extended |= TT2$M_PASTHRU | TT2$M_ALTYPEAHD;
- if (parity)
- cccbrk.basic |= TT$M_NOECHO;
- else
- cccbrk.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
- cccbrk.basic &= ~TT$M_ESCAPE; /* Disable escape-seq processing */
- cccbrk.extended &= ~TT2$M_LOCALECHO; /* and local echoing */
- if (!CHECK_ERR("concb: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &cccbrk, sizeof(cccbrk), 0, 0, 0, 0))) return(-1);
- debug(F100,"concb ok","",0);
- return(0);
- }
-
- /* C O N B I N -- Put console in binary mode */
-
- /* Returns 0 if ok, -1 if not */
-
- int
- #ifdef CK_ANSIC
- conbin(char esc)
- #else
- conbin(esc) char esc;
- #endif /* CK_ANSIC */
- /* conbin */ {
-
- debug(F101,"conbin batch","",batch);
- if (batch) return(0);
- if (!cgmf) congm(); /* Get modes if necessary. */
- escchr = esc; /* Make this available to other fns */
- ckxech = 1; /* Program can echo characters */
- ccraw.extended |= TT2$M_PASTHRU | TT2$M_ALTYPEAHD;
- ccraw.basic &= ~TT$M_ESCAPE; /* Disable escape-seq processing */
- ccraw.extended &= ~TT2$M_LOCALECHO; /* and local echoing */
- if (parity)
- ccraw.basic |= TT$M_NOECHO;
- else
- ccraw.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
- ccraw.basic &= ~(TT$M_HOSTSYNC | TT$M_TTSYNC);
- if (!CHECK_ERR("conbin: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ccraw, sizeof(ccraw), 0, 0, 0, 0))) return(-1);
- return(0);
- }
-
-
- /* C O N R E S -- Restore the console terminal */
-
- int
- conres() {
- debug(F101,"conres cgmf","",cgmf);
- if (!cgmf) return(0); /* Do nothing if modes unknown */
- if (batch) return(0);
-
- msleep(250); /* not known! */
- ckxech = 0; /* System should echo chars */
- if (!CHECK_ERR("conres: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &ccold, sizeof(ccold), 0, 0, 0, 0))) return(-1);
- debug(F100,"conres ok","",0);
- return(0);
- }
-
-
- /* C O N R E S N E -- Restore the console terminal with No Echo */
-
- int
- conresne() {
- debug(F101,"conresne cgmf","",cgmf);
- if (!cgmf) return(0); /* Don't do anything if modes unk */
- if (batch) return(0);
-
- msleep(250);
- ckxech = 1; /* Program should echo chars */
-
- cctmp = ccold;
- cctmp.basic |= TT$M_NOECHO;
- if (!CHECK_ERR("conres: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SETMODE, &wrk_iosb, 0, 0,
- &cctmp, sizeof(cctmp), 0, 0, 0, 0))) return(-1);
- debug(F100,"conresne ok","",0);
- return(0);
- }
-
- /* C O N O C -- Output a character to the console terminal */
-
- int
- #ifdef CK_ANSIC
- conoc(char c)
- #else
- conoc(c) char c;
- #endif /* CK_ANSIC */
- /* conoc */ {
- if (batch) putchar(c);
- else
- if (!CHECK_ERR("conoc: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_WRITEVBLK|IO$M_BREAKTHRU,
- &wrk_iosb, 0, 0, &c, 1, 0, 0, 0, 0))) return(-1);
- return(1);
- }
-
- /* C O N X O -- Write x characters to the console terminal */
-
- int
- conxo(x,s) char *s; int x; {
- if (batch) fprintf(stdout, "%.*s", x, s);
- else if (!CHECK_ERR("conxo: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_WRITEVBLK|IO$M_BREAKTHRU,
- &wrk_iosb, 0, 0, s, x, 0, 0, 0, 0))) return(-1);
- return(0);
- }
-
- /* C O N O L -- Write a line to the console terminal */
-
- int
- conol(s) char *s; {
- int len;
-
- if (batch) fputs(s, stdout);
- else {
- len = strlen(s);
- if (!CHECK_ERR("conol: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_WRITEVBLK|IO$M_BREAKTHRU, &wrk_iosb,
- 0, 0, s, len, 0, 0, 0, 0))) return(-1);
- }
- return(1);
- }
-
- /* C O N O L A -- Write an array of lines to console, with CRLFs added */
-
- int
- conola(s) char *s[]; {
- int i;
- char t[100], *cp;
-
- for (i=0 ; *s[i] ; i++) {
- strncpy(t,s[i],100);
- for (cp = t + strlen(t); --cp >= t;) {
- if (*cp != '\n' && *cp != '\r') {
- cp++;
- *cp++ = '\r'; *cp++ = '\n'; *cp++ = '\0';
- break;
- }
- }
- conol(t);
- }
- return(0);
- }
-
- /* C O N O L L -- Output a string followed by CRLF */
-
- int
- conoll(s) char *s; {
- conol(s);
- conol("\r\n");
- return(1);
- }
-
-
- /* C O N C H K -- Check if characters available at console */
-
- int
- conchk() {
- struct {
- unsigned short count;
- unsigned char first;
- unsigned char reserved1;
- long reserved2;
- } t;
-
- if (batch || backgrd) return(0);
- return(CHECK_ERR("conchk: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, IO$_SENSEMODE|IO$M_TYPEAHDCNT, &wrk_iosb,
- 0, 0, &t, sizeof(t), 0, 0, 0, 0)) ? t.count : 0);
- }
-
- /* C O N I N C -- Get a character from the console */
-
- int
- coninc(timo) int timo; {
- int n = 0;
- unsigned char ch;
- int func, mask;
-
- if (batch) return(getchar());
- mask = 1 << CON_EFN;
- if (con_queued) {
- if (timo > 0) {
- struct { int hi, lo; } qtime;
- qtime.hi = -10*1000*1000*timo; /* Max about seven minutes */
- qtime.lo = -1;
- sys$setimr(TIM_EFN, &qtime, 0, 0);
- mask |= TIM_EFN;
- }
- sys$wflor(CON_EFN, mask);
- sys$readef(CON_EFN, &mask);
- if (mask & (1 << CON_EFN)) {
- ch = (unsigned char) conch;
- CHECK_ERR("coninc: coniosb.status", coniosb.status);
- con_queued = 0;
- } else {
- ch = -1;
- vms_status = SS$_TIMEOUT;
- }
- } else {
- func = IO$_READVBLK | IO$M_NOFILTR;
- if (timo > 0) func |= IO$M_TIMED;
- CHECK_ERR("coninc: sys$qiow",
- sys$qiow(QIOW_EFN, conchn, func, &wrk_iosb,0,0,&ch,1,timo,0,0,0));
- }
- if (ch == '\r') ch = '\n';
-
- if (vms_status & 1) return(ch);
- return(-1);
- }
-
-
- /* V M S _ G E T C H A R -- get a character from the console (no echo).
- * Since we use raw reads, we must check for ctrl/c, ctrl/y and
- * ctrl/z ourselves. We probably should post a "mailbox" for
- * ctrl/c and ctrl/y so the poor user can abort a runaway Kermit.
- * Note: this routine intends for ctrl/z (eof) to be "permanent".
- * Currently, no kermit routine calls "clearerror". If this
- * changes, the following code must be rewritten.
- */
-
- int
- vms_getchar() {
- register unsigned int ch;
- static int ateof = 0;
-
- if (ateof)
- return (EOF);
- ch = coninc(0);
- switch (ch) {
- case ('Y' - 64):
- case ('C' - 64):
- #ifndef COMMENT
- /*
- Just call the same handler that signal(SIGINT,xxx) would have invoked
- if Ctrl-C had been trapped. The pointer to the handler was saved in
- cctrap by conint().
- */
- if (cctrap)
- (*cctrap)(SIGINT,0);
- #else
- ttclos(ttyfd); /* Close down other terminal */
- conres(); /* And cleanup console modes */
- exit(SS$_ABORT); /* Fatal exit. */
- #endif /* COMMENT */
- case ('Z' - 64):
- ateof = 1;
- return (EOF);
-
- default:
- return (ch);
- }
- }
-
- /* C O N T T I -- Get character from console then from tty */
- /*
- This is used in conect() when NO_FORK is defined.
- src is returned with 1 if the character came from the comm. line,
- 0 if it was from the console, and with -1 if there was any error.
- */
- #ifdef TCPIPLIB
- /*
- * Network/console read posted?
- */
- static int nettty_queued = 0;
- static int netcon_queued = 0;
- #endif /* TCPIPLIB */
-
- int
- contti(c, src) int *c, *src; {
-
- #ifndef TCPIPLIB
- int mask = 1<<CON_EFN | 1<<TTY_EFN;
- int x; unsigned char cc;
-
- #else /* TCPIPLIB */
-
- #define NET_EFN 7 /* Network event flag */
-
- int mask; /* Event flag mask */
-
- static CHAR concc; /* Console and network data */
- static CHAR netcc;
-
- static struct iosb_struct net_iosb;
- static struct iosb_struct con_iosb; /* IO status blocks */
-
- /*
- Buffered network data, count, next character. Declared in CKCNET.C ...
- */
- extern CHAR ttibuf[];
- extern int ttibn;
- extern int ttibp;
- #endif /* TCPIPLIB */
-
- *src = -1; /* Assume there was an error */
-
- #ifdef TCPIPLIB
- if (network) { /* For active network connections */
- debug(F100,"contti network","",0);
-
- if (ttibn > 0) {
- /*
- * Handle the case where data remains in our "internal" buffer.
- * We need to:
- *
- * -- Handle the console keyboard (is a character ready?)
- * -- Return one character from the network buffer if not
- *
- * Post a new console read if necessary
- */
- if (!netcon_queued) {
- if (!CHECK_ERR("contti: console sys$qio",
- sys$qio(CON_EFN, conchn, IO$_READVBLK,
- &con_iosb, 0, 0, &concc, 1,
- 0, 0, 0, 0))) return(-1);
- netcon_queued = 1;
- }
- /*
- * Console character ready?
- */
- (void) sys$readef(CON_EFN, &mask);
-
- if (mask & (1 << CON_EFN)) {
- /*
- * Yes, return it
- */
- netcon_queued = 0;
-
- if (!CHECK_ERR("contti: con_iosb.status",
- con_iosb.status)) return(-1);
-
- *c = concc & 0xff;
- *src = 0;
- return(1);
- }
- /*
- * No console data; return buffered network character
- */
- ttibn--;
- *c = ttibuf[ttibp++];
- *src = 1;
- return(1);
- }
- /*
- * No buffered data; post network and console reads
- */
- if (!nettty_queued) {
- /* -lt. 1992-09-14 begin */
- /* All the event flag numbers should be obtained using lib$get_ef().
- * Using hard coded numbers, especially < 31 is tres dangerous!!!
- * Be careful, one must also change the event flag cluster used by
- * sys$readef. It is *not* just a simple matter of changing a few #defines.
- *
- * At least for DEC TCP/IP Services, socket calls return a proper file
- * descriptor (fd). OpenVMS system services require a channel
- * (from sys$assign). The two are *not* the same. The call vaxc$get_sdc()
- * maps from a DEC TCP/IP fd to a channel.
- *
- * This is "gag me with a spoon" code, but it gets thing up and running.
- *
- */
- #ifdef DEC_TCPIP
-
- {
- static int last_ttyfd = -1;
- static short int net_chan = -1;
-
- if (ttyfd != last_ttyfd){
- last_ttyfd = ttyfd;
- #ifdef __DECC
- net_chan = (short) decc$get_sdc(last_ttyfd);
- #else
- #ifdef VAXC
- net_chan = vaxc$get_sdc(last_ttyfd);
- #else
- # error CALL TO GET_SDC requires DECC or VAXC compiler!
- #endif /* VAXC */
- # endif /* DECC */
- }
-
- if (!CHECK_ERR("contti: network sys$qio",
- sys$qio(NET_EFN, net_chan, IO$_READVBLK, &net_iosb, 0, 0,
- &netcc, 1, 0, 0, 0, 0))) return(-1);
- }
-
- #else /* Not DEC_TCPIP */
-
- if (!CHECK_ERR("contti: network sys$qio",
- sys$qio(NET_EFN, ttyfd, IO$_READVBLK, &net_iosb, 0, 0,
- &netcc, 1, 0, 0, 0, 0))) return(-1);
- #endif /* DEC_TCPIP */
- nettty_queued = 1;
- }
-
- if (!netcon_queued) {
- if (!CHECK_ERR("contti: console sys$qio",
- sys$qio(CON_EFN, conchn, IO$_READVBLK, &con_iosb,
- 0, 0, &concc, 1, 0, 0, 0, 0))) return(-1);
- netcon_queued = 1;
- }
- /*
- * Wait for a character
- */
- mask = (1 << CON_EFN) | (1 << NET_EFN);
-
- if (!CHECK_ERR("contti: sys$wflor",
- sys$wflor(CON_EFN, mask))) return(-1);
-
- if (!CHECK_ERR("contti: sys$readef",
- sys$readef(CON_EFN, &mask))) return(-1);
-
- if (mask & (1 << CON_EFN)) {
- /*
- * Console
- */
- if (!CHECK_ERR("contti: con_iosb.status",
- con_iosb.status)) return(-1);
-
- *c = concc & 0xff;
- *src = 0;
- netcon_queued = 0;
-
- } else if (mask & (1 << NET_EFN)) {
- /*
- * Network
- */
- if (!(net_iosb.status & 1)) {
- /*
- * Network read error
- */
- #ifdef WINTCP
- _$set_vaxc_error(SS$_NORMAL, net_iosb.status);
- win$perror("contti: net_iosb.status");
- #else
- #ifdef MULTINET
- #ifdef COMMENT
- /*
- When user hangs up, this prints an unnecessary scary message,
- like "Operation would block."
- */
- socket_perror("contti: net_iosb.status");
- #endif /* COMMENT */
- #endif /* MULTINET */
- #endif /* WINTCP */
- return(-1);
- }
-
- if (net_iosb.size == 0) {
- /*
- * Handle reset from remote
- */
- return(-1);
- }
- *c = netcc & 0xff;
- *src = 1;
- nettty_queued = 0;
- }
- } else /* Not network */
- #endif /* TCPIPLIB */
-
- /*
- Should we worry about a network connection that's running under BATCH ?
- */
- if (batch) { /* Batch? */
- debug(F100,"contti batch","",0);
- if ((*c = getchar()) != EOF) {
- *src = 0;
- } else {
- *src = 1;
- *c = ttinc(0);
- }
- } else { /* Interactive but not network */
-
- #ifdef TTXBUF
- if (ttxbn > 0) { /* Buffered port chars available */
-
- /* Post a read on the console if one is not posted already */
-
- if (!con_queued) {
- if (!CHECK_ERR("contti: console sys$qio",
- sys$qio(CON_EFN, conchn, IO$_READVBLK,
- &coniosb, 0, 0,
- &conch, 1, 0, 0, 0, 0)))
- return(-1);
- con_queued = 1;
- }
-
- /* See if a console character has been read and if so, return it. */
-
- (void) sys$readef(CON_EFN, &mask);
- if (mask & (1 << CON_EFN)) {
- con_queued = 0;
- if (!CHECK_ERR("contti: coniosb.status",
- coniosb.status))
- return(-1);
- *c = conch & 0xff;
- *src = 0;
- return(1);
- }
-
- /* No console character, so return buffered port character */
-
- *c = ttinc(0);
- *src = 1;
- return(1);
- }
-
- /* No buffered port data; post both network and console reads... */
-
- #endif /* TTXBUF */
-
- mask = 1<<CON_EFN | 1<<TTY_EFN; /* Event mask */
-
- debug(F101,"contti interactive mask","",mask);
-
- if (!con_queued) { /* Console read not queued... */
- if (!CHECK_ERR("contti: console sys$qio",
- sys$qio(CON_EFN, conchn, IO$_READVBLK, &coniosb, 0, 0,
- &conch, 1, 0, 0, 0, 0))) return(-1);
- con_queued = 1;
- debug(F100,"contti con_queued","",0);
- }
- if (!tt_queued) { /* Port read not queued */
- if (!CHECK_ERR("contti: tty sys$qio",
- sys$qio(TTY_EFN, ttychn, IO$_READVBLK, &ttiosb, 0, 0,
- &ttch, 1, 0, 0, 0, 0))) return(-1);
- tt_queued = 1;
- debug(F100,"contti tt_queued","",0);
- }
-
- /* Wait for one of the queued reads to complete */
-
- if (!CHECK_ERR("contti: sys$wflor",
- sys$wflor(CON_EFN, mask))) return(-1);
- debug(F100,"contti sys$wflor ok","",0);
-
- /* Read the event flags to see which read was completed */
-
- if (!CHECK_ERR("contti: sys$readef",
- sys$readef(CON_EFN, &mask))) return(-1);
- debug(F100,"contti sys$readef ok","",0);
-
-
- /* Return the character with the appropriate source (src) indicator */
-
- if (!(*src = ((mask & 1<<CON_EFN) ? 0 : 1))) {
- *c = conch;
- CHECK_ERR("contti: coniosb.status", coniosb.status);
- con_queued = 0;
- } else {
- *c = (ttprty ? ttch & 0177 : ttch);
- if (ttiosb.status == SS$_HANGUP) {
- fprintf(stderr,"\n%%CKERMIT-F-HANGUP, data set hang-up");
- *src = -1;
- return(1);
- }
- CHECK_ERR("contti: ttiosb.status", ttiosb.status);
- tt_queued = 0;
- }
- if (!(vms_status & 1)) *src = -1;
- }
- debug(F101,"contti *src","",*src);
- return((*src > -1) ? 1 : 0);
- }
-
- /*
- C A N C I O
- Cancel pending I/O requests on console and communication device.
- */
- VOID
- cancio() {
- #ifdef NETCONN
- if (network) {
- #ifdef TCPIPLIB
- #ifdef DEC_TCPIP
- short int net_chan = -1;
- #ifdef __DECC
- net_chan = (short) decc$get_sdc(ttyfd);
- #else
- #ifdef VAXC
- net_chan = vaxc$get_sdc(ttyfd);
- #else
- # error CALL TO GET_SDC requires DECC or VAXC compiler!
- #endif /* VAXC */
- # endif /* DECC */
- if (nettty_queued) (void) sys$cancel(net_chan);
- #else
- if (nettty_queued) (void) sys$cancel(ttyfd);
- #endif /* DEC_TCPIP */
- if (netcon_queued) (void) sys$cancel(conchn);
-
- netcon_queued = 0;
- nettty_queued = 0;
- return;
- #else /* Not TCPIPLIB */
- return;
- #endif /* TCPIPLIB */
- }
- #endif /* NETCONN */
-
- if (!batch) {
- CHECK_ERR("cancio: console sys$cancel",
- sys$cancel(conchn));
- CHECK_ERR("cancio: tty sys$cancel",
- sys$cancel(ttychn));
- con_queued = 0;
- tt_queued = 0;
- }
- }
-
- /* get_qio_maxbuf_size()
- *
- * Get maximum size of QIO that can occur without getting the dreaded
- * exceeded quota status.
- */
-
- #ifndef SYI$_MAXBUF
- #define SYI$_MAXBUF 4175
- #endif /* SYI$_MAXBUF */
-
- int
- get_qio_maxbuf_size(ttychn) unsigned long int ttychn; {
- unsigned char *tmpbuf;
- int unsigned long max=0;
- struct itmlst syiitm[] = { {2,SYI$_MAXBUF,(char *)&max,0},
- {0,0,0,0}};
-
- if (!ttychn) return(-1);
-
- if (!CHECK_ERR("get_qio_maxbuf_size: sys$getsyiw",
- sys$getsyiw( 0 /* efn */
- ,0 /* csidadr */
- ,0 /* nodename */
- ,&syiitm /* itmlst */
- ,&wrk_iosb /* iosb */
- ,0 /* astadr */
- ,0))) /* astprm */
- exit(SS$_ABORT); /* Fatal exit */
-
- if (!(tmpbuf = malloc(max)))
- return(0);
-
- for (; max > 0; max -= 16) {
- if (!test_qio(ttychn,max,tmpbuf)) /* (was &tmpbuf, caused crash) */
- {
- free(tmpbuf);
- return(max);
- }
- }
-
- free(tmpbuf);
- printf("\n%%CKERMIT-F-get_qio_maxbuf_size, Could not get maxbuf size\n");
- exit(SS$_ABORT); /* Fatal exit */
- }
-
- int
- test_qio(ttychn,max,dest)
- unsigned long int ttychn;
- long int max;
- unsigned char *dest;
- {
- static int trmmsk[2] = {0,0};
-
- /* trmmsk[1] = 1 << eol; */
-
- vms_status = sys$qiow(QIOW_EFN, ttychn, IO$_READVBLK|IO$M_TIMED,
- &wrk_iosb, 0, 0, dest, max, 0, &trmmsk, 0, 0);
- return( !(vms_status & 1) ||
- (!(wrk_iosb.status & 1)) && wrk_iosb.status != SS$_TIMEOUT);
- }
-
-
- /*
- * Flush tt output buffer
- */
-
- int
- ttfluo() {
-
- long n=0;
-
- #ifdef NETCONN
- if (network) return(0);
- #endif /* NETCONN */
-
- if (!ttychn) return(-1); /* Not open. */
-
- if (!CHECK_ERR("ttfluo: sys$qiow",
- sys$qiow(QIOW_EFN, ttychn, IO$_READVBLK|IO$M_TIMED|IO$M_PURGE,
- &wrk_iosb, 0, 0, &n, 0, 0, 0, 0, 0))) {
- perror("flush failed");
- return(-1);
- }
- return(0);
- }
-
- /* T T G M D M -- Get modem signals */
- /*
- Looks for the modem signals CTS, DSR, and CTS, and returns those that are
- on in as its return value, in a bit mask as described for ttwmdm. Returns:
- -3 Not implemented
- -2 if the line does not have modem control
- -1 on error.
- >= 0 on success, with a bit mask containing the modem signals that are on.
- */
- int
- ttgmdm() {
- struct {
- unsigned char type;
- unsigned char spare1;
- unsigned char modem;
- unsigned char spare2;
- unsigned long filler;
- } mdminfo;
- int retval;
-
- #ifdef NETCONN
- if (network) return(-2);
- #endif /* NETCONN */
- vms_status = sys$qiow(QIOW_EFN, ttychn, IO$_SENSEMODE|IO$M_RD_MODEM,
- &wrk_iosb, 0, 0, &mdminfo, 0, 0, 0, 0, 0);
-
- if (vms_status != SS$_NORMAL) {
- debug(F101,"ttgmdm serious error, status","",vms_status);
- return(-1);
- }
-
- debug(F101,"ttgmdm iosb","",wrk_iosb.status);
- debug(F101,"ttgmdm type","",mdminfo.type);
- debug(F101,"ttgmdm modem","",mdminfo.modem);
-
- if (wrk_iosb.status != SS$_NORMAL) {
- debug(F101,"ttgmdm iosb error, status","",wrk_iosb.status);
- return(-1);
- }
-
- #ifdef DT$_LAT
- if (mdminfo.type == DT$_LAT) {
- debug(F101,"ttgmdm LAT port, no modem control","",0);
- return(-2);
- }
- #endif /* DT$_LAT */
-
- if (mdminfo.type == 0) {
- debug(F101,"ttgmdm unknown driver, modem","",mdminfo.modem);
- return(-2);
- }
-
- retval = BM_DTR | BM_RTS; /* Not visible, set by TTDRIVER */
- if (mdminfo.modem & TT$M_DS_CTS)
- retval |= BM_CTS;
- if (mdminfo.modem & TT$M_DS_DSR)
- retval |= BM_DSR;
- if (mdminfo.modem & TT$M_DS_CARRIER)
- retval |= BM_DCD;
- if (mdminfo.modem & TT$M_DS_RING)
- retval |= BM_RNG;
- return(retval);
- }
-
- /*
- * Return tty speed. Speed is retreived from a qiow initially.
- * It is then changed only at user request.
- */
- long
- ttgspd() {
- extern int speed;
- #ifdef NETCONN
- if (network) return(-1); /* -1 if network connection */
- #endif /* NETCONN */
- return(speed);
- }
-
-
- /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
- *
- * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
- * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
- * 2 = Auto: For "modem direct": The same as "Off".
- * For real modem types: Heed carrier during connect, but ignore
- * it anytime else. Compatible with pre-5A C-Kermit versions.
- *
- * As you can see, this setting does not affect dialing, which always ignores
- * carrier (unless there is some special exception for some modem type). It
- * does affect ttopen() if it is set before ttopen() is used. This setting
- * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
- * (or should be) always called before any communications is tried, which
- * means that, practically speaking, the effect is immediate.
- *
- * Of course, nothing of this applies to remote mode (xlocal = 0).
- *
- * Someone has yet to uncover how to manipulate the carrier in the BSD
- * environment (or any non-termio using environment). Until that time, this
- * will simply be a no-op for BSD.
- *
- * Note that in previous versions, the carrier was most often left unchanged
- * in ttpkt()/ttvt() unless they were called with DIALING or CONNECT. This
- * has changed. Now it is controlled by ttcarr in conjunction with these
- * modes.
- */
- int
- ttscarr(carrier) int carrier; {
-
- return(-1);
- }
-
- int
- psuspend(x) int x; {
-
- return(-1);
- }
-
- #ifdef CK_CURSES
- /*
- tgetent() support for VMS curses emulation.
- Used by all three VMS fullscreen methods.
- Called from "SET FILE DISPLAY FULLSCREEN" in ckuus7.c.
- */
- int isvt52 = 0; /* VT52/VT1xx flag */
-
- int
- tgetent(lp, term) char *lp, *term; {
- debug(F101,"tgetent terminal type","",ccold.type);
- debug(F101,"tgetent terminal extended","",ccold.extended);
-
- if ((ccold.type == DT$_VT5X) || (ccold.type == DT$_VT55)) {
- debug(F100,"tgetent VT5x","",0);
- isvt52 = 1;
- return(1);
- }
- if ((ccold.extended & TT2$M_ANSICRT) == TT2$M_ANSICRT) {
- debug(F100,"tgetent ANSICRT","",0);
- isvt52 = 0;
- return(1);
- }
- if ((ccold.extended & TT2$M_DECCRT) == TT2$M_DECCRT) {
- debug(F100,"tgetent DECCRT","",0);
- isvt52 = 0;
- return(1);
- }
- return(0); /* Not a supported terminal type */
- }
- #endif /* CK_CURSES */
-